import pandas as pd
import numpy as np

def simple_ma_strategy(data, stop_loss_rate, cost, fee_rate, drawdown_rate, take_profit_rate):
    print("普通版均线策略2")
    short_window = 5
    long_window = 20

    # 检查必要列是否存在
    required_columns = ['收盘', '日期']
    for col in required_columns:
        if col not in data.columns:
            raise ValueError(f"输入数据缺少必要列 {col}")

    # 处理可能的缺失值
    data = data.dropna(subset=['收盘'])
    #print("接收到的交易策略止损率: " + str(stop_loss_rate))

    # 检查数据量是否足够
    if len(data) < max(short_window, long_window):
        print(f"数据量不足，当前数据长度为 {len(data)}，短期窗口为 {short_window}，长期窗口为 {long_window}")
        return data, {}, []

    # 计算短期和长期均线
    data['short_ma'] = data['收盘'].rolling(window=short_window).mean()
    data['long_ma'] = data['收盘'].rolling(window=long_window).mean()

    # 用收盘价填充因初始数据不足导致的 NaN 值
    data['short_ma'] = data['short_ma'].fillna(data['收盘'])
    data['long_ma'] = data['long_ma'].fillna(data['收盘'])

    # 手动计算 MACD 指标
    ema_12 = data['收盘'].ewm(span=12, adjust=False).mean()
    ema_26 = data['收盘'].ewm(span=26, adjust=False).mean()
    data['macd'] = ema_12 - ema_26
    data['signal'] = data['macd'].ewm(span=9, adjust=False).mean()
    data['hist'] = data['macd'] - data['signal']

    # 初始化信号列
    data['signal'] = 0  # 0 表示无操作
    data['position'] = 0  # 持仓状态，0 表示空仓，1 表示持仓
    data['stop_loss'] = False  # 止损标记
    data['reason'] = ''  # 买卖理由
    data['holding_days'] = 0  # 持仓天数

    # 初始持仓状态和买入价格
    position = 0
    buy_price = 0
    buy_date_index = None
    win_count = 0
    loss_count = 0
    trade_count = 0
    total_fee = 0
    cash = cost
    portfolio_values = []
    holding_days_list = []
    max_profit = 0
    max_profit_rate = 0
    max_loss = 0
    max_loss_rate = 0
    total_return = 0
    annual_return = 0
    # 新增死叉计数器
    death_cross_count = 0

    for i in range(1, len(data)):
        if position == 0:
            # 金叉判断，同时检查 MACD 是否在水上
            if data.loc[i, 'short_ma'] > data.loc[i, 'long_ma'] and data.loc[i - 1, 'short_ma'] <= data.loc[i - 1, 'long_ma']:
                if pd.notna(data.loc[i, 'macd']) and data.loc[i, 'macd'] >= 0:
                    data.loc[i, 'signal'] = 1
                    data.loc[i, 'direction'] = '买入'
                    data.loc[i, 'reason'] = '金叉且 MACD 水上买入'
                    position = 1
                    buy_price = data.loc[i, '收盘']
                    buy_date_index = i
                    high_price = buy_price  # 记录买入后的最高价格
                    hands = int(cash / (data.loc[i, '收盘'] * 100))  # Calculate the number of hands
                    shares = hands * 100
                    trade_amount = shares * data.loc[i, '收盘']
                    fee = trade_amount * fee_rate
                    cash -= trade_amount + fee
                    total_fee += fee
                    data.loc[i, 'hands'] = hands
                    data.loc[i, 'trade_amount'] = trade_amount
                    data.loc[i, 'fee'] = fee
                    trade_count += 1
                    # 买入时重置死叉计数器
                    death_cross_count = 0
        elif position == 1:
            # 止损判断
            current_price = data.loc[i, '收盘']
            stop_loss_price = buy_price * (1 - stop_loss_rate)
            if current_price <= stop_loss_price:
                data.loc[i, 'signal'] = -1
                data.loc[i, 'direction'] = '卖出'
                data.loc[i, 'reason'] = '止损卖出'
            # 止盈判断
            if take_profit_rate and take_profit_rate > 0:
                profit_rate = (current_price - buy_price) / buy_price
                if profit_rate >= take_profit_rate:
                    data.loc[i, 'signal'] = -1
                    data.loc[i, 'direction'] = '卖出'
                    data.loc[i, 'reason'] = '止盈卖出'
            # 回撤判断，当 drawdown_rate 不为 0 时才进行判断
            if drawdown_rate and drawdown_rate > 0:
                high_price = max(high_price, current_price)
                drawdown = (high_price - current_price) / high_price
                if drawdown >= drawdown_rate:
                    data.loc[i, 'signal'] = -1
                    data.loc[i, 'direction'] = '卖出'
                    data.loc[i, 'reason'] = '回撤卖出'
            # 死叉判断
            if data.loc[i, 'short_ma'] < data.loc[i, 'long_ma'] and data.loc[i - 1, 'short_ma'] >= data.loc[i - 1, 'long_ma']:
                death_cross_count += 1
                if death_cross_count >= 2:
                    data.loc[i, 'signal'] = -1
                    data.loc[i, 'direction'] = '卖出'
                    data.loc[i, 'reason'] = '第二次死叉卖出'
            # 执行卖出操作
            if data.loc[i, 'signal'] == -1:
                trade_amount = shares * data.loc[i, '收盘']
                fee = trade_amount * fee_rate
                cash += trade_amount - fee
                total_fee += fee
                # 修正收益计算公式
                profit = trade_amount - shares * buy_price - fee
                profit_ratio = (profit / (shares * buy_price)) * 100
                holding_days = i - buy_date_index
                holding_days_list.append(holding_days)
                data.loc[i, 'hands'] = hands
                data.loc[i, 'trade_amount'] = trade_amount
                data.loc[i, 'fee'] = fee
                data.loc[i, 'profit'] = profit
                data.loc[i, 'profit_ratio'] = profit_ratio
                data.loc[i, 'holding_days'] = holding_days
                if profit > 0:
                    win_count += 1
                    if profit > max_profit:
                        max_profit = profit
                        max_profit_rate = profit_ratio
                else:
                    loss_count += 1
                    if profit < max_loss:
                        max_loss = profit
                        max_loss_rate = profit_ratio
                position = 0
                shares = 0
                trade_count += 1
                # 卖出后重置死叉计数器
                death_cross_count = 0

        # Update portfolio value
        if position == 1:
            portfolio_value = cash + shares * data.loc[i, '收盘']
        else:
            portfolio_value = cash
        portfolio_values.append(portfolio_value)

    # Calculate final portfolio value
    final_value = portfolio_values[-1] if portfolio_values else cost
    total_return = ((final_value - cost) / cost) * 100
    # 简单年化收益率计算，假设一年 252 个交易日
    num_days = len(data)
    annual_return = ((1 + total_return / 100) ** (252 / num_days) - 1) * 100 if num_days > 0 else 0

    avg_holding_days = sum(holding_days_list) / len(holding_days_list) if holding_days_list else 0
    max_holding_days = max(holding_days_list) if holding_days_list else 0
    min_holding_days = min(holding_days_list) if holding_days_list else 0

    # Calculate profit probability
    profit_probability = (win_count / trade_count * 100) if trade_count > 0 else 0

    # 计算盈利金额
    #profit_amount = final_value - cost

    # Build the quantitative result dictionary in the desired order
    quant_result = {
        "初始资金": cost,
        "盈利": final_value - cost,
        #"盈利金额": profit_amount,  # 新增盈利金额项
        "最终资金": final_value,
        "总收益率": total_return,
        "年化收益率": annual_return,
        "交易笔数": trade_count,
        "盈利笔数": win_count,
        "亏损笔数": loss_count,
        "盈利概率": profit_probability,
        "最大盈利": max_profit,
        "最大盈利率": max_profit_rate,
        "最大亏损": max_loss,
        "最大亏损率": max_loss_rate,
        "平均持仓天数": avg_holding_days,
        "最大持仓天数": max_holding_days,
        "最小持仓天数": min_holding_days,
        "手续费总金额": total_fee,
    }

    # 提取有买卖信号的数据行作为交易详情，保留 hands 列
    trade_detail_data = data[data['signal'] != 0][[
        '日期', 'direction', 'hands', 'trade_amount', 'fee', 'reason', 'profit', 'profit_ratio', 'holding_days'
    ]]
    trade_detail_data = trade_detail_data.sort_values(by='日期', ascending=False)
    # 将 trade_detail_data 转换为文本框可显示的分行文本，保留 hands 信息
    # 修改标题为中文
    trade_detail_text = "日期, 交易方向, 手数, 交易金额, 手续费, 交易理由, 盈利金额, 盈利率, 持仓天数\n"
    if not trade_detail_data.empty:
        for _, row in trade_detail_data.iterrows():
            profit = row['profit'] if pd.notna(row['profit']) and row['direction'] == '卖出' else 0
            profit_ratio = row['profit_ratio'] if pd.notna(row['profit_ratio']) and row['direction'] == '卖出' else 0
            trade_detail_text += (
                f"{row['日期'].strftime('%Y-%m-%d')}, {row['direction']}, {int(row['hands'])}, "
                f"{row['trade_amount']:.2f}, {row['fee']:.2f}, {row['reason']}, {profit:.2f}, "
                f"{profit_ratio:.2f}%, {int(row['holding_days'])} 天\n"
            )
    else:
        trade_detail_text += "无交易详情\n"

    # 打印量化结果
    #print("\n量化结果:")
    #for key, value in quant_result.items():
    #    print(f"{key}: {value}")

    # 打印交易详情
    #print("\n交易详情:")
    #print(trade_detail_text)

    # 生成交易指令
    data['position_change'] = data['signal'].diff()

    # 筛选并打印 signal 不等于 0 且不为空的明细
    non_zero_signal_data = data[data['signal'].notna() & (data['signal'] != 0)]
    #print("signal 不等于 0 且不为空的明细：")
    #print(non_zero_signal_data[['日期', 'signal', 'position', 'reason', 'holding_days']])

    # 导出 data 为 CSV 文件
    data.to_csv('simple_ma_strategy_result.csv', index=False)
    print(f"simple_ma_strategy 返回的 data 类型: {type(data).__name__}")
    return data, quant_result, trade_detail_text